Flow.genXml = function(fo){
	var ns = fo.nodes, n, t1 = "\t", t2 = "\t\t", t3 = "\t\t\t", t4 = "\t\t\t\t";
	
	function get(v, m, n) {
		if (v) {
			return v;
		}
		var c = n? (((n.m && n.m.caption) || (n.d && (n.d.name || n.d.code)) || n.t) + '的') : '',
			e = c + (m || '属性') + '未定义';
		alert(e);
		throw e;
	}
	
	// Find p1 to match p0 from node n
	function match(n, p0, p1, l, ca) {
		ca = ca || {}; // checked nodes
		do {
			if (n.t) {
				var c = (n.d || {}).code;
				if (!c) {
					continue; // Is code missing?
				}
				if (ca[c]) {
					return; // Is checked?
				}
				ca[c] = 1;
				//
				if (n.t == p0) {
					l++; // Begin another one
				} else if (n.t == p1) {
					if (l) {
						l--; // End another pair
					} else {
						return c;
					}
				}
			} else {
				// For each multi-branches, such as Fork/If
				for (var k in n) {
					var a = ns[k];
					if (!a) {
						continue;
					}
					c = match(a, p0, p1, l, ca);
					if (c) {
						return c; // If any branch be closed
					}
				}
				return;
			}
		} while (n = nn(n));
		return;
	}
	
	function props(pp, t) {
		var xml = '', t = t || t2;
		$.each(pp || {}, function (i, p){
			xml +=  t + '<property name="' + p.code
				+ '" ' + (p.type == 'ref' ? 'ref':'value')
				+ '="' + p.value + '" />' + "\n";
		});
		return xml;
	}
	
	function handler(d, t) {
		if (!d.impl) {
			return '';
		}
		var xml = '', t = t || t2;
		if (d.impl.indexOf('.') >= 0) {
			xml += t + '<property name="handler">' + "\n";
			xml += t + t1 + '<bean class="' + d.impl + '">' + "\n";
			xml += props(d.pp, t4);
			xml += t + t1 + '</bean>' + "\n";
			xml += t + '</property>' + "\n";
		} else {
			xml += t + '<property name="handler" ref="' + d.impl + '" />' + "\n";
		}
		return xml;
	}
	
	function wrapper(d, t) {
		var xml = '', t = t || t2;
		if (d.wrapper){
			xml += t + '<property name="wrapper">' + "\n";
			xml += t + t1 + '<bean class="' + d.wrapper + '">' + "\n";
			xml += props(d.pm, t4);
			xml += t + t1 + '</bean>' + "\n";
			xml += t + '</property>' + "\n";
//		} else {
//			xml += t + '<property name="wrapper" ref="defaultWrapper" />' + "\n";
		}
		return xml;
	}
	
	function status(c, t) {
		var xml = '', t = t || t2;
		if (c && c.status == '1'){
			xml += t + '<property name="status" value="'  + c.status +  '" />' + "\n";
		}
		return xml;
	}
	
	function id(n) {
		return get(fo.d.code, '流程编号') + '-' + get(n.d.code, '节点编号', n);
	}
	
	function next(n, t) {
		var c = get(n.d.code, '节点编号', n);
		return (t || t2) + '<property name="next" value="' + n.d.code + '' + '" />' + "\n";
	}
	
	function prop(k, v, t) {
		var xml = '', t = t || t2;
		if (k && v) {
			xml += t + '<property name="' + k + '" value="' + v +'" />' + "\n";
		}
		return xml;
	}

	function nn(n) {
		if (n.n || n.t == 'end') {
			return n.n;
		}
		var e = ((n.m && n.m.caption) || (n.d && (n.d.name || n.d.code)) || n.id) + '缺少后继';
		alert(e);
		throw e;
	}

	function nnn(n) {
		return nn(nn(n));
	}

	var xml = '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
		+ '<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"' + "\n"
		+ ' xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"' + "\n"
		+ ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans' + "\n"
		+ '	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd' + "\n"
		+ '	http://www.springframework.org/schema/tx' + "\n"
		+ '	http://www.springframework.org/schema/tx/spring-tx-4.0.xsd' + "\n"
		+ '	http://www.springframework.org/schema/context' + "\n"
		+ '	http://www.springframework.org/schema/context/spring-context-4.0.xsd' + "\n"
		+ '	http://www.springframework.org/schema/aop' + "\n"
		+ '	http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">' + "\n\n";
	for (var i=1; i<ns.length; i++) {
		n = ns[i];
		if (!n || !n.d || n.d.o) {
			continue;
		}
		switch(n.t) {
		case 'end'://结束节点
		case 'arrow':
			break;
		case 'start'://开始节点
			var c = get(fo.d.code, '流程编号');
			xml += t1 + '<bean id="' + c + 'Service" parent="simpleFlowService">' + '\n';
			xml += '\t\t' + '<property name="flowId" value="'  + c + '"/>' + "\n";
			xml += '\t' +'</bean>'+ "\n\n";
			
			xml += t1 + '<bean id="' + c + '" parent="simpleFlow" >' + "\n";
			xml += prop('flowId', c);
			xml += prop('timeout', fo.d.timeout);
			xml += prop('ver', fo.d.ver);
			xml += prop('mutex', fo.d.mutex? 'true':'false');
			xml += prop('revCode', fo.d.revCode);
			xml += prop('revType', fo.d.revType);

			if (fo.d.persister) {
				xml += t2 + '<property name="persister" ref="' + fo.d.persister + '" />' + "\n";
			}

			n = nnn(n);
			xml += prop('entry', get(n.d.code, '节点编号', n));
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'process':
			xml += t1 + '<bean id="' + id(n) + '" parent="processNode">' + "\n";
			
			xml += wrapper(n.d);
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			xml += prop('entry', n.d.entry);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'input':
			xml += t1 + '<bean id="' + id(n) + '" parent="inputNode">' + "\n";
			
			xml += prop('ui', n.d.uiCode);
			xml += status(n.c);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'output':
			xml += t1 + '<bean id="' + id(n) + '" parent="outputNode">' + "\n";
			
			xml += prop('ui', n.d.uiCode);
			xml += status(n.c);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'judge':
			xml += t1 + '<bean id="' + id(n) + '" parent="judgeNode">' + "\n";
			
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			xml += prop('expression', n.d.exprCode);
			
			n = nn(n);
			for (var k in n) {
				var z = n[k], t = z.d.tagCode, d = z.n.d;
				if (t == 'yes') {
					xml += prop('yes', d.code);
				} else if (t == 'no') {
					xml += prop('no', d.code);
				}
			}
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'switch':
			xml += t1 + '<bean id="' + id(n) + '" parent="switchNode">' + "\n";
			
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			
			if (n.d.exprCode) {
				xml += prop('expression', n.d.exprCode);
			}
			xml += t2 + '<property name="branches">' + "\n";
			xml += t3 + '<map>' + "\n";

			var p = n;
			n = nn(n);
			for (var k in n) {
				var z = n[k], t = get(z.d.tagCode, 'Switch的分支编号'), d = z.n.d;
				xml += t4 + '<entry key="' + t + '" value="' + d.code + '" />' + "\n";
			}
			xml += t3 + '</map>' + "\n";
			xml += t2 + '</property>' + "\n";
			xml += t1 + '</bean>' + "\n\n";
			
			break;
		case 'try':
			var _catch = match(nn(n), 'try', 'catch', 0);
			var _finally = match(nn(n), 'try', 'finally', 0);
			var _yrt = match(nn(n), 'try', 'yrt',0);
			
			xml += '\t' + '<bean id="' + id(n) + '" parent="tryNode">' + '\n';
			
			xml += prop('next', nnn(n).d.code);
			xml += status(n.c);
			
			if (_catch || _finally){
				if (_catch) {
					xml += prop('catch', _catch);
				}
				if (_finally) {
					xml += prop('finally', _finally);;
				}
			} else {
				alert('Try块需要Catch或Finally');
			}
			if (_yrt){
				xml += prop('yrt', _yrt);;
			} else {
				alert('Try块需结束标识Yrt')
			}
			xml += '\t' + '</bean>' +'\n\n';
			break;
		case 'catch':
			xml += t1 + '<bean id="' + id(n) + '" parent="catchNode">' + "\n";
			
			xml += status(n.c);
			
			n = nnn(n);
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'finally':
			xml += t1 + '<bean id="' + id(n) + '" parent="finallyNode">' + "\n";
			
			xml += status(n.c);
			
			n = nnn(n);
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'yrt':
			xml += t1 + '<bean id="' + id(n) + '" parent="yrtNode">' + "\n";
			
			xml += status(n.c);
			
			n = nnn(n);
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break
		case 'fork':
			var join = match(nn(n), 'fork', 'join', 0);
			xml += t1 + '<bean id="' + id(n) + '" parent="forkNode">' + "\n";
			
			xml += prop('join', join);
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			xml += prop('timeout', n.d.timeout);
			
			xml += t2 + '<property name="branches">' + "\n";
			xml += t3 + '<set>' + "\n";

			var p = n;
			n = nn(n);
			for (var k in n) {
				//console.log(k);
				var z = n[k], d = z.n.d;
				xml += t4 + '<value>' + d.code +'</value>' + "\n";
			}
			xml += t3 + '</set>' + "\n";
			xml += t2 + '</property>' + "\n";
			
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'join':
			xml += t1 + '<bean id="' + id(n) + '" parent="joinNode">' + "\n";
			
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'subflow':
			xml += t1 + '<bean id="' + id(n) + '" parent="subflowNode">' + "\n";
			
			xml += wrapper(n.d);
			xml += status(n.c);
			xml += prop('ref', n.d.ref);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'beginTx':
			xml += t1 + '<bean id="' + id(n) + '" parent="beginTxNode">' + "\n";
			
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('timeout', n.d.timeout);
			
			var commitTx = match(nn(n), 'beginTx', 'commitTx',0);
			xml += prop('commitTx', commitTx);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'commitTx':
			xml += t1 + '<bean id="' + id(n) + '" parent="commitTxNode">' + "\n";

			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		case 'suspend':
			xml += t1 + '<bean id="' + id(n) + '" parent="suspendNode">' + "\n";
			
			xml += handler(n.d);
			xml += status(n.c);
			xml += prop('revCode', n.d.revCode);
			
			n = nnn(n); // 取下一节点
			xml += next(n);
			xml += t1 + '</bean>' + "\n\n";
			break;
		}
	}
	xml += '</beans>';
	return xml;
}